/**
 * ...
 * @author Krzysztof Rozalski
 */

package hapi.db;
#if php
import php.db.ResultSet;
#end

class MysqlHapiResultSet implements ResultSet {
	
	var resultSet:ResultSet;
	var orginalConvert:String->String->Dynamic;
	public var length(getLength,null) : Int;
	public var nfields(getNFields,null) : Int;

	public function new(resultSet:ResultSet) {
		this.resultSet = resultSet;
	}
	
	public function hasNext() {
		var cache =  Reflect.field(resultSet, "cache");
		if ( cache == null ) {
			cache = next();
			Reflect.setField(resultSet, "cache", cache);
		}
		return (cache != null);
	}
	
	//! WARNING - Heavy reflection usage
	public function next() : Dynamic {
		var cache =  Reflect.field(resultSet, "cache");
		if( cache != null ) {
			Reflect.setField(resultSet, "cache", null);
			return cache;
		}
		var fetchRow = Reflect.field(resultSet, "fetchRow");
		var fetchResult:Dynamic = Reflect.callMethod(resultSet, fetchRow, []);
		if(!fetchResult) return null;
		var o : Dynamic = { };
		var getFieldsDescription = Reflect.field(resultSet, "getFieldsDescription");
		var descriptions =  Reflect.callMethod(resultSet, getFieldsDescription, []);
		var cRow:Dynamic = Reflect.field(resultSet, "cRow");
		for (i in 0...nfields)
			Reflect.setField(o, descriptions[i].name, convert(cRow[i], descriptions[i].type));
		return o;
	}
	
	private function convert(v : String, type : String) : Dynamic {
		var orginalConvert = Reflect.field(resultSet, "convert");
		var result = Reflect.callMethod(resultSet, orginalConvert, [v, type]);
		if ( type == "timestamp" ) return v == null ? null : Date.fromString(v);
		if ( type == "int" && Std.string(result) != v ) return v;//over int range->return original value
		else return result;
	}
	
	public function results() : List<Dynamic> {
		var l = new List();
		while( hasNext() )
			l.add(next());
		return l;
	}
	
	public function getResult( n : Int ) : String {
		return resultSet.getResult(n);
	}
	
	public function getIntResult( n : Int ) : Int {
		return resultSet.getIntResult(n);
	}
	
	public function getFloatResult( n : Int ) : Float {
		return resultSet.getFloatResult(n);
	}
	
	function getLength() {
		return resultSet.length;
	}
	
	function getNFields() {
		return resultSet.nfields;
	}
}